package com.fushenlan.epidemicControl.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fushenlan.commons.GeneralResponse;
import com.fushenlan.dto.CacheReqDTO;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;

/**
 * @author Administrator
 * @date 2022/5/4 3:00
 */
@Api(tags = "微信授权登录接口")
@Slf4j
@RestController
@RequestMapping("/cache")
public class CacheController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @PostMapping("/clearByKey")
    public GeneralResponse<?> clearByKey(@RequestBody CacheReqDTO cacheReqDTO) {
        if (cacheReqDTO == null) {
            return GeneralResponse.fail("-2", "请传入参数", "");
        }
        Object result = null;
        if (StrUtil.isNotBlank(cacheReqDTO.getDeleteKey())) {
            //删除单个key
            result = redisTemplate.delete(cacheReqDTO.getDeleteKey());
            log.info("redis key:{} delete key result:{}", cacheReqDTO.getDeleteKey(), result);
        }
        //删除某个key开头的所有key
        if (StrUtil.isNotBlank(cacheReqDTO.getDeleteKeysLike())) {
            result = deleteKeysLike(cacheReqDTO.getDeleteKeysLike());
        }
        //批量删除key
        if (CollUtil.isNotEmpty(cacheReqDTO.getBatchKeys())) {
            result = redisTemplate.delete(cacheReqDTO.getBatchKeys());
            log.info("redis keyList:{} delete keyList result:{}", JSONUtil.toJsonStr(cacheReqDTO.getBatchKeys()), result);
        }
        //清空所有库中数据
        if (StrUtil.isNotBlank(cacheReqDTO.getFlushDbNo())) {
            if (Integer.parseInt(cacheReqDTO.getFlushDbNo()) < 0 || Integer.parseInt(cacheReqDTO.getFlushDbNo()) > 15) {
                return GeneralResponse.fail("-1", "所选数据库不存在", "");
            }
            String luaScript = "redis.call('select',ARGV[1]); " +
                    " redis.call('flushdb');";
            DefaultRedisScript<String> redisScript = new DefaultRedisScript<>();
            redisScript.setResultType(String.class);
            redisScript.setScriptText(luaScript);
            result = redisTemplate.execute(redisScript, Collections.emptyList(), cacheReqDTO.getFlushDbNo());
        }
        return new GeneralResponse<>("0000", "缓存删除结果：" + result, "");
    }

    private Object deleteKeysLike(String keyPrefix) {
        String luaScript = "" +
                "local function scan(key) " +
                "  local cursor = 0 " +
                "  local keynum = 0 " +
                "  local delNum = 0 " +
                "  repeat" +
                "       local res = redis.call('scan', cursor, 'MATCH', key, 'COUNT', ARGV[1]) " +
                "" +
                "       if (res ~= nil and #res >=0) then " +
                "           redis.replicate_commands() " +
                "           cursor = tonumber(res[1]) " +
                "           local ks = res[2] " +
                "           keynum = #ks " +
                "           for i=1,keynum,1 do " +
                "               local k = tostring(ks[i]) " +
                "               delNum = delNum + redis.call('del', k) " +
                "            end " +
                "        end " +
                "  until (cursor <= 0) " +
                "  return delNum " +
                " end " +
                "local a = #KEYS " +
                "local b = 1 " +
                "local total = 0 " +
                "while (b <= a) " +
                "do" +
                "    total = total + scan(KEYS[b]) " +
                "    b = b + 1 " +
                " end " +
                "return total";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptText(luaScript);
        Object execute = redisTemplate.execute(redisScript, Collections.singletonList(keyPrefix + "*"), "1000");
        log.info("删除以某个key开头的所有缓存数量: {}", execute);
        return execute;
    }
}
